package de.uni_stuttgart.ipvs.ids.globalstate;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * A process which collects recorded states of different processes and creates a
 * global state.
 * 
 * @author Team 3/4 Elkhan Dadashov, Ahmed Labib, Dhaval A Shah, Patrick Stortz
 */
public class Collector implements Runnable {
	private int listenPort;
	private int processCount; // for checking if all processes send their states

	// for the output
	double sumStates = 0;;
	double sumChannels = 0;;

	/**
	 * Create a collector.
	 * 
	 * @param listenPort
	 *            The port to listen to for incoming connections
	 * @param processCount
	 *            The amount of processes which will send states to the
	 *            collector
	 */
	public Collector(int listenPort, int processCount) {
		this.listenPort = listenPort;
		this.processCount = processCount;

	}

	@Override
	public void run() {
		try {
			ServerSocket server = new ServerSocket(listenPort);
			int receivedStates = 0;
			ObjectInputStream input = null;
			while (true) {
				// wait for incoming connections
				Socket client = server.accept();

				// get the input stream of the socket connection
				input = new ObjectInputStream(client.getInputStream());

				// read the message from the stream
				Object message = input.readObject();

				// close the input stream
				input.close();

				if (message instanceof RecordedState) {
					// save the received state
					receivedStates++;
					RecordedState state = (RecordedState) message;
					sumStates = sumStates + state.getProcessBalance();
					sumChannels = sumChannels + state.getAmountInAllChannels();
					if (receivedStates == processCount) {
						Thread.sleep(1000);
						break;
					}
				} else {
					System.err
							.println("Error! Collector received an unknown message!");// DEBUG
				}
			}

			// close the socket
			server.close();

		} catch (IOException e) {
			System.err
					.println("Error! Collector cannot receive states from the processes!");// DEBUG
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			System.err
					.println("Error! Collector cannot receive state from a process!");// DEBUG
			e.printStackTrace();
		} catch (InterruptedException e) {
			System.err
					.println("Error! Collector got interrupted while waiting for a connection!");// DEBUG
			e.printStackTrace();
		}
		// call this method after all states were collected
		printToConsole();
	}

	public void printToConsole() {
		System.out.println("------------------------------");
		System.out.println("Total amount of money is: "
				+ (sumStates + sumChannels));
		System.out.println("Total amount of money in states is: " + sumStates);
		System.out.println("Total amount of money in channels is: "
				+ sumChannels);
		System.out.println("------------------------------");
		sumStates = 0;
		sumChannels = 0;
	}

	public String getAddress() {
		try {
			return java.net.InetAddress.getLocalHost().getHostAddress();
		} catch (UnknownHostException e) {
			e.printStackTrace();
			return "localhost";
		}
	}

	public int getPort() {
		return listenPort;
	}

}
